﻿using System;
using System.Linq;
using BingoClientModel;
using BingoServerCommon.Common;
using BingoServerCommon.Helper;
using BingoServerCommon.Log4net;
using HPSocketCS;

namespace BingoHallServerConsole
{
	public class HallTcpPackServer
	{
		public static TcpPackServer Server = new TcpPackServer();

		public void Start(ushort port)
		{
			try
			{
				#region 设置服务器事件

				//连接到达事件
				Server.OnAccept += new TcpServerEvent.OnAcceptEventHandler(OnAccept);
				//数据到达事件
				Server.OnReceive += new TcpServerEvent.OnReceiveEventHandler(OnReceive);
				//连接关闭事件
				Server.OnClose += new TcpServerEvent.OnCloseEventHandler(OnClose);
				//服务器关闭事件
				Server.OnShutdown += new TcpServerEvent.OnShutdownEventHandler(OnShutdown);


				

				#endregion

				// 设置包头标识,与对端设置保证一致性
				Server.PackHeaderFlag = 0xa3;
				// 设置最大封包大小
				Server.MaxPackSize = 0x256;  //byte  

				Server.IpAddress = "0.0.0.0";
				Server.Port = port;
				// 启动服务
				Server.Start();

			}
			catch (Exception e)
			{
				Console.WriteLine("BingoTcpPackServer.Start() 异常");
				LogHelper.WriteFatal("BingoTcpPackServer.Start", e);
			}
		}


		#region 事件


		/// <summary>
		/// 连接到达事件
		/// </summary>
		/// <param name="connId"></param>
		/// <param name="pClient"></param>
		/// <returns></returns>
		HandleResult OnAccept(IntPtr connId, IntPtr pClient)
		{
			// 客户进入了
			Console.WriteLine("有连接到达Hall~~");
			Console.ResetColor();

			// 获取客户端ip和端口
			string ip = string.Empty;
			ushort port = 0;
			if (Server.GetRemoteAddress(connId, ref ip, ref port))
			{
				Console.WriteLine($" > [{connId},OnAccept] -> PASS({ip}:{port})");
			}
			else
			{
				Console.WriteLine($" > [{connId},OnAccept] -> Server_GetClientAddress() Error");
				return HandleResult.Error;
			}
			return HandleResult.Ok;
		}


		/// <summary>
		/// 数据到达事件
		/// </summary>
		/// <param name="connId"></param>
		/// <param name="bytes"></param>
		/// <returns></returns>
		HandleResult OnReceive(IntPtr connId, byte[] bytes)
		{
			try
			{
				bytes = CryptologyHelper.DecryptByteArr(ref bytes);

				// 获取附加数据
				var session = Server.GetExtra<Session>(connId);
				session.Server = Server;
				Console.WriteLine($" > 数据到达  [{session.ConnId},OnReceive] -> {session.IpAddress}:{session.Port} ({bytes.Length} bytes)");
				int id = NetFunction.ntoh(BitConverter.ToInt32(bytes, 0));
				Package pack = PackageFactory.Instance.NewPackage((short)id, bytes);
				pack.Excute(session);

				return HandleResult.Ok;
			}
			catch (Exception)
			{
				return HandleResult.Error;
			}
		}


		/// <summary>
		/// 连接关闭事件
		/// </summary>
		/// <param name="connId"></param>
		/// <param name="enOperation"></param>
		/// <param name="errorCode"></param>
		/// <returns></returns>
		HandleResult OnClose(IntPtr connId, SocketOperation enOperation, int errorCode)
		{
			if (errorCode == 0)
			{
				Console.WriteLine($" > [{connId}, 连接关闭]");
			}
			else
			{
				Console.WriteLine($" > 连接出错 [{connId},连接Error] -> OP:{enOperation},CODE:{errorCode}");
				return HandleResult.Error;
			}
			if (Server.RemoveExtra(connId) == false)
			{
				Console.WriteLine(" > [{0},OnClose] -> Server.RemoveExtra(connId) fail", connId);
				return HandleResult.Error;
			}

			var session = Server.GetExtra<Session>(connId);
			session?.Save(Program.ConnectionPool);

			return HandleResult.Ok;
		}


		/// <summary>
		/// 服务器关闭事件
		/// </summary>
		/// <returns></returns>
		HandleResult OnShutdown()
		{
			Console.WriteLine("服务器关闭");
			return HandleResult.Ok;
		}

		#endregion

		/// <summary>
		/// 
		/// </summary>
		/// <param name="msg"></param>
		public static void BroadCast(string msg)
		{
			//广播
			var id = Server.GetAllConnectionIDs().ToList();
			for (int i = 0; i < id.Count; i++)
			{
				string aa = Guid.NewGuid().ToString();
				Session se = Server.GetExtra<Session>(id[i]);
				//Server.Send(id[i], aa);
				Package pkg = new Package(EnumPackCommand.SC_BroadCastTest);
				pkg.Write("BroadCastTest" + aa);
				se.Send(pkg);
			}
		}
	}
}
